(function(window) {
    "use strict";
    
    // 分析蛇对象
    //  蛇不是一个整体，也是右一节一节组成
    //  属性
    //      1. width： 蛇一节的宽度
    //      2. height： 蛇一节的高度
    //      3. headBgc： 蛇头的背景颜色
    //      4. bodyBgc： 蛇身体的背景颜色
    //      5. body:    蛇每一节的信息（蛇有几节，蛇一节的坐标信息在哪）
    //          
    //  方法
    //      render: 蛇添加到地图上
    //      move:  蛇移动
    //          蛇移动的原理：修改body数组中的蛇每一节的坐标
    //          有两种方式：
    //              1. 需要让蛇的每一节坐标发生改变 ，， 代码使用for循环， 性能差
    //              2. 复制蛇头，删除蛇尾

    function Snake(options) {
        options = options || {};

        this.width = options.width || 20;
        this.height = options.height || 20;
        this.headBgc = options.headBgc || "green";
        this.bodyBgc = options.bodyBgc || "red";

        // 添加蛇移动方向
        this.direction = options.direction || "right";

        this.body = options.body || [
            { x: 11, y: 0 }, // 蛇头的坐标， 蛇头永远是第一项
            { x: 10, y: 0 }, // 蛇头的坐标， 蛇头永远是第一项
            { x: 9, y: 0 }, // 蛇头的坐标， 蛇头永远是第一项
            { x: 8, y: 0 }, // 蛇头的坐标， 蛇头永远是第一项
            { x: 7, y: 0 }, // 蛇头的坐标， 蛇头永远是第一项
            { x: 6, y: 0 }, // 蛇头的坐标， 蛇头永远是第一项
            { x: 5, y: 0 }, // 蛇头的坐标， 蛇头永远是第一项
            { x: 4, y: 0 }, // 蛇头的坐标， 蛇头永远是第一项
            { x: 3, y: 0 }, // 蛇头的坐标， 蛇头永远是第一项
            { x: 2, y: 0 }, // 蛇头的坐标， 蛇头永远是第一项
            { x: 1, y: 0 }, // 蛇中间的坐标
            { x: 0, y: 0 }, // 蛇尾巴的坐标
        ];
    }

    // target 参数： 指的是地图元素
    Snake.prototype.render = function(target) {
        // 蛇添加到地图上

        // 实现思路：
        //  1. 根据蛇的body数组的长度去创建蛇 -- for循环遍历body数组
        //  2. 每遍历一次，创建蛇元素，span元素去表示蛇元素
        //  3. 设置span蛇这一节的样式， 根据 蛇的实例对象去设置的
        //  4. 创建的span添加到地图中

        // this ==>  s;

        // 1.
        for (var i = 0; i < this.body.length; i++) {
            // this.body[i]  ==> 蛇的每一节坐标信息， 是个对象

            // 2.
            var span = document.createElement("span");

            // 3.
            span.style.width = this.width + "px";
            span.style.height = this.height + "px";

            span.innerText = i;


            // 判断span设置蛇头的背景颜色还是身体的背景颜色
            // 根据啥判断：  i == 0 ；  span  表示蛇头
            if (i == 0) {
                // 蛇头
                span.style.backgroundColor = this.headBgc;
            } else {
                // 身体
                span.style.backgroundColor = this.bodyBgc;
            }

            // left  top  一定要定位
            span.style.position = "absolute";

            span.style.left = this.body[i].x * this.width + "px";
            span.style.top = this.body[i].y * this.height + "px";

            // 4.
            target.appendChild(span);
        }
    }

    // target 参数： 指的是地图元素
    Snake.prototype.move = function(target, food) {

        // console.log(food); // food是食物的实例对象，上面有食物的x、y坐标，判断蛇头和食物的坐标有没有重合


        // 做法： 复制蛇头，删除蛇尾
        // 实现思路（步骤）：
        //  1. 复制当前蛇头的坐标，得到一个新的蛇头  newHead
        //  2. 将newHead 添加到body中,加到数组的前面  unshift
        //  3. 根据蛇移动的方向去修改newHead的坐标
        //  4. 把蛇尾删除掉  pop()
        //  以上四个步骤，，仅仅是修改body数组中的坐标，地图中的蛇位置没有发生改变的

        // 根据body数组中的数据重新把蛇渲染到地图中  render方法在调用就行了
        // 在渲染之前，把地图中的所有的蛇（span元素）给找到并且从地图中移出掉。
        // 因为render 方法会根据body数组最新的坐标去渲染蛇添加到地图中


        // this ==> s

        // 1.
        var newHead = {
            x: this.body[0].x,
            y: this.body[0].y
        }

        // 2.
        this.body.unshift(newHead);

        // 3.
        switch (this.direction) {
            case "up":
                // 上
                newHead.y--;
                break;
            case "right":
                // 右
                newHead.x++;
                break;
            case "down":
                // 下
                newHead.y++;
                break;
            case "left":
                // 左
                newHead.x--;
                break;
        };


        // 在第三个步骤之后，来判断蛇有没有吃到食物
        // 判断啥：蛇头的x、y坐标和 食物的x、y坐标是否重合了
        if (newHead.x == food.x && newHead.y == food.y) {
            // 蛇吃到食物了
            // console.log("蛇吃到食物了");
            // 1. 把地图中的食物找到并且移出掉
            // 2. 重复渲染一份食物添加到地图中(只需要调用食物的渲染方法)
            // 3. 蛇增加一节

            // 1.
            var div = target.querySelector("div");
            target.removeChild(div);

            // 2.
            food.render(target);

            // 3. 增加一节，只要不删除蛇尾就行了，代码放在了else语句
        } else {
            // 蛇没有吃到食物

            // 4.
            // 蛇尾删除掉，有条件的，只有在蛇没有吃到食物的时候，就是移动效果
            this.body.pop();
        }


        // console.log(this.body);

        var spans = target.querySelectorAll("span");

        // 坑： removeChild 删除的是元素，spans是一个伪数组，这样删除不了
        // 需要删除的span是存在spans伪数组中
        // map.removeChild(spans);

        // 所以，需要遍历spans，一项一项的取出来删除
        for (var i = 0; i < spans.length; i++) {
            // console.log(spans[i]); ==> 每一个span元素
            target.removeChild(spans[i]);
        }

        // 一定要注意，渲染之前先移出原来的蛇
        // 坑； render方法需要参数的，map，这里一定要传参
        this.render(target);
    }


    window.Snake = Snake;
})(window)
